﻿using IronPython.Hosting;
using MahApps.Metro.Controls;
using Microsoft.Scripting.Hosting;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace LunarSF.SHomeWorkshop.LunarMarkdownEditor
{
    /// <summary>
    /// HtmlFactory.xaml 的交互逻辑
    /// </summary>
    public partial class HtmlFactory : MetroWindow
    {
        public HtmlFactory()
        {
            InitializeComponent();
            this.Title = Globals.AppName + " - Html 工厂";
            tbWorkspacePath.Text = "当前工作区目录：> " + Globals.PathOfWorkspace;
            //tbxRemoveText.Text = "<script>hljs.initHighlightingOnLoad();</script>";
            browser.Navigate(new Uri(Globals.DefaultWorkspacePath + "About-Html-Factory.html"));
        }

        private Encoding GetSelectedResultEncoding()
        {
            if (rdOutputGB2312.IsChecked == true) return Encoding.GetEncoding("gb2312");
            if (rdOutputGBK.IsChecked == true) return Encoding.GetEncoding("GBK");
            if (rdOutputUTF8.IsChecked == true) return Encoding.UTF8;
            return Encoding.GetEncoding("gb18030");
        }

        private int indexOfHtmlFiles = 0;
        private List<string> htmlFilePaths = null;
        private Utils.Web preWeb = null;

        /// <summary>
        /// Get changed(by javascript) html text from previewFrame.
        /// </summary>
        public string GetHtml()
        {
            var header = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n" +
                         "<html xmlns=\"http://www.w3.org/1999/xhtml\" >\n";
            var tail = "\n</html>";
            try
            {
                var html = browser.InvokeScript("getHtml") as string;
                if (string.IsNullOrWhiteSpace(html))
                {
                    return "没有在预览区中找到 Html 文档的内容文本。请检查预览区中是否正在预览 Html 网页文档或 Html 文档的内容是否正确！";
                }
                return $"{header}{html}{tail}";
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }

        private void BtnRun_Click(object sender, RoutedEventArgs e)
        {
            if (preWeb == null)
            {
                var preWeb = new Utils.Web(browser);
            }

            if (htmlFilePaths == null)
            {
                htmlFilePaths = PythonScriptArgs.GetAllFilePathsOfWorkspace("html");
            }

            if (htmlFilePaths.Count > 0)
            {
                indexOfHtmlFiles = 0;  // 默认情况下，indexOfHtmlFiles 为 -1，防止 LoadCompleted 事件无限循环。
                if (System.IO.File.Exists(htmlFilePaths[0]))
                {
                    browser.Navigate(new Uri(htmlFilePaths[0]));
                }
            }
        }

        private static ScriptEngine engine = null;
        private static ScriptScope scope = null;

        private static string FormatByPythonScript(string sourceHtml, string directoryLevelMark, string srcFilePath)
        {
            #region 调用用户编写的、指定为处理后、保存前自动调用的所有Python脚本
            //如果用户编写了指定为“编译前自动调用”的Python脚本文本。
            if (engine == null)
                engine = Python.CreateEngine();
            if (scope == null)
                scope = engine.CreateScope();

            try
            {
                string result = sourceHtml;

                var list = new List<UIElement>();
                foreach (var item in Globals.MainWindow.lbxPythonScripts.Items)
                {
                    var ue = item as UIElement;
                    if (ue != null) list.Add(ue);
                }

                foreach (var item in Globals.MainWindow.lbxWorkspacePythonScripts.Items)
                {
                    var ue = item as UIElement;
                    if (ue != null) list.Add(ue);
                }

                foreach (var item in list)
                {
                    var psli = item as PythonScriptListItem;
                    if (psli == null || psli.CallMode != PythonScriptListItem.PythonScriptCallMode.BeforeHtmlFactoryProcessed) continue;

                    var sourceCode = engine.CreateScriptSourceFromFile(psli.FullPath);
                    // 运行脚本
                    scope.SetVariable("inputText", result);
                    scope.SetVariable("outputText", result);
                    scope.SetVariable("documentText", result);
                    scope.SetVariable("ignoreTextChanging", false);
                    scope.SetVariable("pathToWorkspace", directoryLevelMark);
                    scope.SetVariable("pathOfWorkspace", Globals.PathOfWorkspace);
                    if (srcFilePath.ToLower().EndsWith(".html"))
                        srcFilePath = srcFilePath.Substring(0, srcFilePath.Length - 4) + ".md";
                    var fi = new FileInfo(srcFilePath);
                    scope.SetVariable("psArgs", new PythonScriptArgs()
                    {
                        MdFileInfo = fi,
                    });

                    // 重设搜索路径，默认的不管用
                    var pathList = engine.GetSearchPaths();
                    pathList.Add(Globals.PathOfPythonScripts);
                    pathList.Add(Globals.PathOfWorkspacePythonScripts);
                    pathList.Add(Globals.InstalledPath);
                    engine.SetSearchPaths(pathList);

                    sourceCode.Execute<string>(scope);

                    var ignoreTextChange = scope.GetVariable<bool>("ignoreTextChanging");
                    if (ignoreTextChange == false)
                    {
                        result = scope.GetVariable<string>("outputText");
                    }
                }
                return result;
            }
            catch (Exception ex)
            {
                ExceptionOperations eo = engine.GetService<ExceptionOperations>();
                string error = eo.FormatException(ex);
                LMessageBox.Show(error, Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
                return sourceHtml;
            }
            #endregion

        }

        private void Browser_LoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e)
        {
            if (indexOfHtmlFiles >= 0 && indexOfHtmlFiles <= htmlFilePaths.Count - 1)
            {
                try
                {
                    var changedHtml = GetHtml();
                    if (string.IsNullOrWhiteSpace(tbxRemoveText.Text) == false)
                    {
                        changedHtml = changedHtml.Replace(tbxRemoveText.Text, "");
                    }

                    //<meta http-equiv="X-UA-Compatible" content="IE=Edge"/>
                    var regVersion = new Regex("(?<=(<meta {1,}http-equiv {0,}= {0,}[\"\']X-UA-Compatible[\"\'] {1,}content {0,}= {0,}[\"\']IE {0,}= {0,}))((edge)|([89])|(1[012]))(?=( {0,}[\"\']>))", RegexOptions.IgnoreCase);
                    var ieVersion = "IE8";
                    foreach (var ue in spIEVersions.Children)
                    {
                        var rbtn = ue as RadioButton;
                        if (rbtn == null) continue;

                        if (rbtn.IsChecked == true)
                        {
                            ieVersion = rbtn.Tag.ToString();
                            break;
                        }
                    }

                    var matchVersion = regVersion.Match(changedHtml);
                    if (matchVersion != null && matchVersion.Success && matchVersion.Value.ToLower() != ieVersion.ToLower())
                    {
                        changedHtml = changedHtml.Substring(0, matchVersion.Index) + ieVersion + changedHtml.Substring(matchVersion.Index + matchVersion.Length);
                    }

                    //<meta http-equiv="Content-Type" content="text/html;charset=gb18030">
                    //"(?<=(<meta {1,}http-equiv {0,}= {0,}[\'\"]Content-Type[\'\"] {1,}content {0,}= {0,}[\'\"]text/html; {0,}charset {0,}= {0,}))((gb2312)|(gbk)|(gb18030)|(utf8))(?=([\'\"] {0,}>))"
                    var regEncoding = new Regex("(?<=(<meta {1,}http-equiv {0,}= {0,}[\'\"]Content-Type[\'\"] {1,}content {0,}= {0,}[\'\"]text/html; {0,}charset {0,}= {0,}))((gb2312)|(gbk)|(gb18030)|(utf8))(?=([\'\"] {0,}>))", RegexOptions.IgnoreCase);

                    var htmlEncoding = "GB18030";
                    foreach (var ue in spEncoding.Children)
                    {
                        var rbtn = ue as RadioButton;
                        if (rbtn == null) continue;

                        if (rbtn.IsChecked == true)
                        {
                            htmlEncoding = rbtn.Tag.ToString();
                            break;
                        }
                    }
                    var matchEncoding = regEncoding.Match(changedHtml);
                    if (matchEncoding != null && matchEncoding.Success && matchEncoding.Value.ToLower() != htmlEncoding.ToLower())
                    {
                        changedHtml = changedHtml.Substring(0, matchEncoding.Index) + htmlEncoding + changedHtml.Substring(matchEncoding.Index + matchEncoding.Length);
                    }

                    // 调用 Python 脚本来进行下一步处理。
                    changedHtml = FormatByPythonScript(changedHtml,
                        CustomMarkdownSupport.GetDirectoryLevelMark(htmlFilePaths[indexOfHtmlFiles]),
                        htmlFilePaths[indexOfHtmlFiles]);

                    System.IO.File.WriteAllText(htmlFilePaths[indexOfHtmlFiles], changedHtml, GetSelectedResultEncoding());

                    indexOfHtmlFiles++;
                }
                finally
                {
                    if (indexOfHtmlFiles < htmlFilePaths.Count)
                    {
                        browser.Navigate(new Uri(htmlFilePaths[indexOfHtmlFiles]));
                    }
                    else
                    {
                        indexOfHtmlFiles = -1;
                        htmlFilePaths = null;
                        LMessageBox.Show("当前工作区中所有 Html 文件均已加工完毕。\r\n为保证不会被无意中的预览操作破坏，请立即关闭本窗口并编译 CHM 工程。");

                        var indexHtmlFilePath = Globals.PathOfWorkspace + "_index.html";
                        if (File.Exists(indexHtmlFilePath))
                        {
                            Globals.MainWindow.previewFrame.Source = new Uri(indexHtmlFilePath);
                        }
                    }
                }
            }
        }

        private void BtnHelp_Click(object sender, RoutedEventArgs e)
        {
            browser.Navigate(new Uri(Globals.DefaultWorkspacePath + "About-Html-Factory.html"));
        }
    }
}
